#include <windows.h>
#define _WIN32_IE 0x0600
#include <commctrl.h>

/*
int main( int argc, char * argv[])
{
    CreateThread (NULL, 0,SocketServer::createServer,NULL, 0, NULL); // tworzenie watkow
    system("pause");

    return 0;
}
*/
/*HINSTANCE uchwyt programu
  hPrevInstance powinien zawierać uchwyt poprzedniego wystąpienia aplikacji,
  od wersji systemu Windows 95 wynosi on zawsze NULL.
  lpCmdLine zawiera liniê poleceñ, z jakiej został uruchomiony nasz program.
   LPSTR to po prostu synonim typu char*
   Ogólnie wszystkie typy z przedrostkiem P lub LP oznaczają w WinAPI wskaźniki.
   nCmdShow określa, jaki powinien być stan okna naszego programu.

   LP long pointer
*/

// Globalne deklaracje uchwytów do okien, kontrolek i programu

    // uchwyt do instancji aplikacji
    HINSTANCE hMainAppInst;

    HWND hMainWindow;
    HWND hStartButton;
    HWND hStopButton;
    HWND hStaticField;
    HWND hZamknijButton;

// Deklaracja funkcji do obsługi zdarzeń
LRESULT CALLBACK GlowneProcedury(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

#include "SocketServer.h"
#include "bd.h"

int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    INITCOMMONCONTROLSEX icex;
    icex.dwSize=sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC=ICC_BAR_CLASSES;
    InitCommonControlsEx(&icex);

    hMainAppInst = hInstance;

    WNDCLASS wndclass; //struktura zawierająca informacje o klasie naszego okna

    wndclass.style = CS_HREDRAW | CS_VREDRAW; //Flaga ta powoduje, ¿e gdy zmienimy rozmiar okna, ca³e okno zostaje na nowo odrysowane.
    //Flaga ta powoduje, ¿e gdy zmienimy rozmiar okna, zostaje odrysowany obszar roboczy okna(wnêtrze okna, bez paska tytu³owego i bocznych ramek, je¿eli takie s¹).

    wndclass.lpfnWndProc = GlowneProcedury; // procedura obsługująca okno
    wndclass.cbClsExtra = 0; //cbClsExtra określa rozmiar dodatkowych danych przynależnych do klasy

    //określa rozmiar dodatkowych danych przynależnych do konkretnych instancji klasy.
    //Zajęty (niekoniecznie zaalokowany) obszar ma zawsze rozmiar: cbClsExtra + ilość_okien * cbWndExtra.
    wndclass.cbWndExtra = 0;

    wndclass.hInstance = hInstance; //aplikacja która jest właścicielem okna

    //kursor aplkacji. gdzie ma szukac null-zasoby systemowe, idc_arrow systemowy kursor
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);

    // Pobiera uchwyt do jednego ze zdefiniowanych zasobów systemu: pióra, pędzla, czcionki lub palety
    wndclass.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wndclass.lpszMenuName = NULL; //menu okna w pliku zasobów. w programie brak menu
    wndclass.lpszClassName = "GlowneOkno"; //nazwa klasy
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); //MAKEINTRESOURCE makro do ładowania zasobu

    if(RegisterClass(&wndclass) == 0)
    {
        MessageBox( NULL, "Nie udalo sie zarejestrowac okna", "RegisterClass", MB_ICONEXCLAMATION | MB_OK );
        return FALSE;
    }

    hMainWindow = CreateWindow(
        "GlowneOkno",
        "Serwer",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        500,
        300,
        NULL,
        NULL,
        hInstance,
        NULL
    );

    if( hMainWindow == NULL )
    {
        MessageBox( NULL, "Nie zostal utworzony uchwyt do glownego okna.", "Uchwyt", MB_ICONEXCLAMATION );
        return FALSE;
    }

    ShowWindow(hMainWindow, SW_SHOW);
    UpdateWindow(hMainWindow);

    MSG msgs; // zmienna do przechowywania komunikatów

    while(GetMessage(&msgs,0,0,0))
    //pętla obsługująca wymianę komunikatów
    {
        TranslateMessage(&msgs);
        //funkcja tłumacząca sygnały z klawiatury na odpowiednie komunikaty systemowe

        DispatchMessage(&msgs);
        //funkcja przetwarzająca komunikaty systemowe przez procedury obsługi
    }

    return msgs.wParam;
}

// OBSŁUGA ZDARZEŃ
LRESULT CALLBACK GlowneProcedury(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_CREATE:
            //funkcja tworząca kontrolkę
            hStartButton = CreateWindow("BUTTON", "Start", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP, 70, 200, 100, 50, hwnd, NULL, hMainAppInst, NULL);
            hStopButton = CreateWindow("BUTTON", "Stop", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP, 200, 200, 100, 50, hwnd, NULL, hMainAppInst, NULL);
            hStaticField = CreateWindow("STATIC", "Status serwera", WS_CHILD | WS_VISIBLE, 50, 100, 400, 20, hwnd, NULL, hMainAppInst, NULL);
            hZamknijButton = CreateWindow("BUTTON", "Zamknij", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP, 330, 200, 100, 50, hwnd, NULL, hMainAppInst, NULL);
            break;

        //polecenia dla komunikatu WM_PAINT
        case WM_PAINT:
            UpdateWindow(hMainWindow);

            break;

        case WM_COMMAND:
            if((HWND)lParam == hStartButton)
            {
                SetWindowText(hStaticField, "Serwer zostal uruchomiony.");
                CreateThread (NULL, 0,SocketServer::createServer,NULL, 0, NULL); // tworzenie watkow
            }
        //jeżeli został naciśnięty przycisk o identyfikatorze numer 1 wyświetli się komunikat

            if((HWND)lParam == hStopButton)
            {
                SetWindowText(hStaticField, "Serwer zostal zatrzymany.");
                SocketServer::ShutdownServer();
            }

            if((HWND)lParam == hZamknijButton)
            {
                SocketServer::ShutdownServer();
                DestroyWindow( hwnd );
                DestroyWindow(hStartButton);
                DestroyWindow(hStopButton);
                DestroyWindow(hStaticField);
                DestroyWindow(hZamknijButton);
                PostQuitMessage( 0 );
            }

            break;
        //polecenia dla komunikatu WM_CLOSE
        case WM_CLOSE:
            SocketServer::ShutdownServer();
            DestroyWindow( hwnd );
            DestroyWindow(hStartButton);
            DestroyWindow(hStopButton);
            DestroyWindow(hStaticField);
            DestroyWindow(hZamknijButton);
            break;

        case WM_DESTROY:
            SocketServer::ShutdownServer();
            DestroyWindow( hwnd );
            DestroyWindow(hStartButton);
            DestroyWindow(hStopButton);
            DestroyWindow(hStaticField);
            DestroyWindow(hZamknijButton);
            PostQuitMessage( 0 );
            break;

        default:
        //domyślna obsługa reszty komunikatów
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }

  return 0;
}
